package repository

import (
	"context"
	"fmt"
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm"
	"techoiceness.com/aiagent/llm-gateway/internal/entity"
)

type clientMessageRepository struct {
	db *gorm.DB
}

// NewClientMessageRepository 创建客户端消息仓库实例
func NewClientMessageRepository(db *gorm.DB) ClientMessageRepository {
	return &clientMessageRepository{db: db}
}

// CreateClientMessage 创建客户端消息
func (r *clientMessageRepository) CreateClientMessage(ctx context.Context, clientMessage *entity.ClientMessage) error {
	if err := r.db.WithContext(ctx).Create(clientMessage).Error; err != nil {
		return fmt.Errorf("failed to create client message: %w", err)
	}
	return nil
}

// UpdateClientMessage 更新客户端消息
func (r *clientMessageRepository) UpdateClientMessage(ctx context.Context, clientMessage *entity.ClientMessage) error {
	if err := r.db.WithContext(ctx).Save(clientMessage).Error; err != nil {
		return fmt.Errorf("failed to update client message: %w", err)
	}
	return nil
}

// GetClientMessageByID 根据ID获取客户端消息
func (r *clientMessageRepository) GetClientMessageByID(ctx context.Context, id uuid.UUID) (*entity.ClientMessage, error) {
	var clientMessage entity.ClientMessage
	if err := r.db.WithContext(ctx).First(&clientMessage, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("client message not found")
		}
		return nil, fmt.Errorf("failed to get client message: %w", err)
	}
	return &clientMessage, nil
}

// GetClientMessageHistory 获取对话的客户端消息历史
func (r *clientMessageRepository) GetClientMessageHistory(ctx context.Context, conversationID uuid.UUID, limit, offset int) ([]entity.ClientMessage, error) {
	var clientMessages []entity.ClientMessage

	query := r.db.WithContext(ctx).
		Where("conversation_id = ?", conversationID).
		Order("created_at ASC")

	if limit > 0 {
		query = query.Limit(limit)
	}
	if offset > 0 {
		query = query.Offset(offset)
	}

	if err := query.Find(&clientMessages).Error; err != nil {
		return nil, fmt.Errorf("failed to get client message history: %w", err)
	}

	return clientMessages, nil
}

// GetClientMessagesByUserID 获取用户的消息历史
func (r *clientMessageRepository) GetClientMessagesByUserID(ctx context.Context, userID uuid.UUID, limit, offset int) ([]entity.ClientMessage, error) {
	var clientMessages []entity.ClientMessage

	query := r.db.WithContext(ctx).
		Where("user_id = ?", userID).
		Order("created_at DESC")

	if limit > 0 {
		query = query.Limit(limit)
	}
	if offset > 0 {
		query = query.Offset(offset)
	}

	if err := query.Find(&clientMessages).Error; err != nil {
		return nil, fmt.Errorf("failed to get client messages: %w", err)
	}

	return clientMessages, nil
}

// DeleteClientMessage 删除客户端消息
func (r *clientMessageRepository) DeleteClientMessage(ctx context.Context, id uuid.UUID) error {
	result := r.db.WithContext(ctx).Delete(&entity.ClientMessage{}, id)
	if result.Error != nil {
		return fmt.Errorf("failed to delete client message: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("client message not found")
	}
	return nil
}

// GetClientMessageCount 获取对话中客户端消息总数
func (r *clientMessageRepository) GetClientMessageCount(ctx context.Context, conversationID uuid.UUID) (int64, error) {
	var count int64
	if err := r.db.WithContext(ctx).
		Model(&entity.ClientMessage{}).
		Where("conversation_id = ?", conversationID).
		Count(&count).Error; err != nil {
		return 0, fmt.Errorf("failed to count client messages: %w", err)
	}
	return count, nil
}

// CleanupOldClientMessages 清理旧的客户端消息
func (r *clientMessageRepository) CleanupOldClientMessages(ctx context.Context, before time.Time) (int64, error) {
	result := r.db.WithContext(ctx).
		Where("created_at < ?", before).
		Delete(&entity.ClientMessage{})

	if result.Error != nil {
		return 0, fmt.Errorf("failed to cleanup old client messages: %w", result.Error)
	}

	return result.RowsAffected, nil
}

// GetClientMessageConversationSummary 获取对话摘要信息
func (r *clientMessageRepository) GetClientMessageConversationSummary(ctx context.Context, conversationID uuid.UUID) (*ConversationSummary, error) {
	var result struct {
		Count     int64
		FirstTime time.Time
		LastTime  time.Time
	}

	err := r.db.WithContext(ctx).
		Model(&entity.ClientMessage{}).
		Select("COUNT(*) as count, MIN(created_at) as first_time, MAX(created_at) as last_time").
		Where("conversation_id = ?", conversationID).
		Scan(&result).Error

	if err != nil {
		return nil, fmt.Errorf("failed to get client message conversation summary: %w", err)
	}

	if result.Count == 0 {
		return nil, fmt.Errorf("conversation not found")
	}

	return &ConversationSummary{
		ConversationID: conversationID,
		MessageCount:   result.Count,
		FirstMessage:   result.FirstTime,
		LastMessage:    result.LastTime,
	}, nil
}

// GetMessagesByPairID 根据消息对ID获取关联的消息（user和assistant）
func (r *clientMessageRepository) GetMessagesByPairID(ctx context.Context, pairID uuid.UUID) ([]entity.ClientMessage, error) {
	var messages []entity.ClientMessage

	if err := r.db.WithContext(ctx).
		Where("message_pair_id = ?", pairID).
		Order("created_at ASC").
		Find(&messages).Error; err != nil {
		return nil, fmt.Errorf("failed to get messages by pair ID: %w", err)
	}

	return messages, nil
}

// GetAssistantMessageByPairID 获取用户消息对应的助手消息
func (r *clientMessageRepository) GetAssistantMessageByPairID(ctx context.Context, pairID uuid.UUID) (*entity.ClientMessage, error) {
	var message entity.ClientMessage

	if err := r.db.WithContext(ctx).
		Where("message_pair_id = ? AND role = ?", pairID, "assistant").
		First(&message).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, fmt.Errorf("failed to get assistant message by pair ID: %w", err)
	}

	return &message, nil
}

// GetUserMessageByPairID 获取助手消息对应的用户消息
func (r *clientMessageRepository) GetUserMessageByPairID(ctx context.Context, pairID uuid.UUID) (*entity.ClientMessage, error) {
	var message entity.ClientMessage

	if err := r.db.WithContext(ctx).
		Where("message_pair_id = ? AND role = ?", pairID, "user").
		First(&message).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, fmt.Errorf("failed to get user message by pair ID: %w", err)
	}

	return &message, nil
}
